package net.simpleframework.swing;

import java.awt.Component;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Window;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ContainerAdapter;
import java.awt.event.ContainerEvent;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.JDialog;
import javax.swing.JEditorPane;
import javax.swing.JTextArea;

/**
 * 这是一个开源的软件，请在LGPLv3下合法使用、修改或重新发布。
 * 
 * @author 陈侃(cknet@126.com, 13910090885)
 *         http://code.google.com/p/simpleframework/
 *         http://www.simpleframework.net
 */
@SuppressWarnings("serial")
public abstract class EnhancedDialog extends JDialog {
	private boolean enterOk = false;

	protected Dimension size;

	private KeyHandler keyHandler;

	protected Object[] elements;

	public EnhancedDialog(final Window owner, final String title, final Object... element) {
		super(owner, title);
		init(element);
	}

	protected void cancel() {
		dispose();
	}

	protected abstract void createUI();

	private void init(final Object... element) {
		elements = element;

		((Container) getLayeredPane()).addContainerListener(new ContainerHandler());
		getContentPane().addContainerListener(new ContainerHandler());

		keyHandler = new KeyHandler();
		addKeyListener(keyHandler);
		addWindowListener(new WindowHandler());

		addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(final ComponentEvent e) {
				if (size != null) {
					final int width = Math.max(getSize().width, size.width);
					final int height = Math.max(getSize().height, size.height);
					setSize(width, height);
				}
			}
		});

		setModal(true);
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);

		createUI();

		initSize();
		setLocationRelativeTo(getOwner());
		setVisible(true);
	};

	private void initSize() {
		if (size != null) {
			super.setSize(size);
		} else {
			pack();
			size = getSize();
		}
	}

	public void ok() {
	}

	public void setEnterOk(final boolean enterOk) {
		this.enterOk = enterOk;
	}

	class ContainerHandler extends ContainerAdapter {

		private void componentAdded(final Component comp) {
			comp.addKeyListener(keyHandler);
			if (comp instanceof Container) {
				final Container cont = (Container) comp;
				cont.addContainerListener(this);
				final Component[] comps = cont.getComponents();
				for (final Component element : comps) {
					componentAdded(element);
				}
			}
		}

		@Override
		public void componentAdded(final ContainerEvent evt) {
			componentAdded(evt.getChild());
		}

		private void componentRemoved(final Component comp) {
			comp.removeKeyListener(keyHandler);
			if (comp instanceof Container) {
				final Container cont = (Container) comp;
				cont.removeContainerListener(this);
				final Component[] comps = cont.getComponents();
				for (final Component element : comps) {
					componentRemoved(element);
				}
			}
		}

		@Override
		public void componentRemoved(final ContainerEvent evt) {
			componentRemoved(evt.getChild());
		}
	}

	class KeyHandler extends KeyAdapter {
		@Override
		public void keyPressed(final KeyEvent evt) {
			if (evt.isConsumed()) {
				return;
			}
			if (evt.getKeyCode() == KeyEvent.VK_ESCAPE) {
				cancel();
				evt.consume();
			} else if (evt.getKeyCode() == KeyEvent.VK_ENTER) {
				final Component cmp = evt.getComponent();
				if (enterOk && !((cmp instanceof JEditorPane) || (cmp instanceof JTextArea))) {
					ok();
				}
			}
		}
	}

	class WindowHandler extends WindowAdapter {
		@Override
		public void windowClosing(final WindowEvent evt) {
			cancel();
		}
	}
}
